//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  File:  disk.c
//
//	Programer: Visual.Wei
//	Date: 2007-4-28
//
#include <eboot.h>

#include <VFLBuffer.h>
#include <WMRTypes.h>
#include <WMRconfig.h>
#include <FTL.h>
#include <VFL.h>
#include <FIL.h>
#include <WMR_bootpart.h>

DWORD BLK_Init()
{
	Buffer *pBuf;
	INT32 	nRet;
	LowFuncTbl *pLowFuncTbl;
	UINT32	nSig;
	UINT32  pTotalScts;

	nRet = FIL_Init();

	if (nRet != FIL_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	OALMSG(OAL_INFO,(TEXT("[FTL:MSG] FIL_Init			[OK]\n")));

	nRet = BUF_Init();

	if (nRet != BUF_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	OALMSG(OAL_INFO,(TEXT("[FTL:MSG] BUF_Init			[OK]\n")));

	nRet = VFL_Init();

	if (nRet != VFL_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	OALMSG(OAL_INFO,(TEXT("[FTL:MSG] VFL_Init			[OK]\n")));

	nRet = FTL_Init();

	if (nRet != FTL_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	OALMSG(OAL_INFO,(TEXT("[FTL:MSG] FTL_Init			[OK]\n")));

	pBuf = BUF_Get(BUF_MAIN_AND_SPARE);

	if (pBuf == NULL)
	{
		return WMR_CRITICAL_ERROR;
	}

	pLowFuncTbl = FIL_GetFuncTbl();

	nRet = pLowFuncTbl->Read(0, Signature_Ppn, BITMAP_FULL_PAGE, 0x3,
	                         pBuf->pData, pBuf->pSpare, FALSE32, TRUE32);

#if	0

	if ( nRet == FIL_U_ECC_ERROR )		// hmseo-061028
	{
		pLowFuncTbl->Erase(0, 0, 0x3);
		nRet = pLowFuncTbl->Read(0, Signature_Ppn, BITMAP_FULL_PAGE, 0x3,
		                         pBuf->pData, pBuf->pSpare, FALSE32, TRUE32);
	}	// hmseo-061028
#endif

	nSig = *(UINT32 *)(pBuf->pData);

	BUF_Release(pBuf);

	if (nRet == FIL_SUCCESS_CLEAN)
	{
		UINT32	nRetTemp;
		UINT32 *pTemp;

		OALMSG(OAL_INFO,(TEXT("[FTL:MSG] Not Formated !\n")));

		nRetTemp = VFL_Format();

		if (nRetTemp != VFL_SUCCESS)
		{
			return WMR_CRITICAL_ERROR;
		}

		OALMSG(OAL_INFO,(TEXT("[FTL:MSG] VFL_Format			[OK]\n")));

		nRetTemp = FTL_Format();

		if (nRetTemp != FTL_SUCCESS)
		{
			return WMR_CRITICAL_ERROR;
		}

		OALMSG(OAL_INFO,(TEXT("[FTL:MSG] FTL_Format			[OK]\n")));

		pBuf = BUF_Get(BUF_MAIN_AND_SPARE);

		if (pBuf == NULL)
		{
			return WMR_CRITICAL_ERROR;
		}

		pTemp= (UINT32 *)(pBuf->pData);

		*pTemp= WMR_SIGNATURE;

		pLowFuncTbl->Write(0, Signature_Ppn, BITMAP_FULL_PAGE, 0x3, pBuf->pData, pBuf->pSpare);

		BUF_Release(pBuf);

		nRetTemp = pLowFuncTbl->Sync(0, FALSE32);

		if (nRetTemp != FIL_SUCCESS)
		{
			return WMR_CRITICAL_ERROR;
		}

		nSig = WMR_SIGNATURE;

		OALMSG(OAL_INFO,(TEXT("[FTL:MSG] Write Signature		[OK]\n")));

	}
	else if (nRet != FIL_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	if (nSig != WMR_SIGNATURE)
	{
		OALMSG(OAL_INFO,(TEXT("[FTL:ERR] Version Fail			[OK]\n")));
		return WMR_CRITICAL_ERROR;
	}

	nRet = VFL_Open();

	if (nRet != VFL_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	OALMSG(OAL_INFO,(TEXT("[FTL:MSG] VFL_Open			[OK]\n")));

	nRet = FTL_Open(&pTotalScts);

	if (nRet != FTL_SUCCESS)
	{
		return WMR_CRITICAL_ERROR;
	}

	OALMSG(OAL_INFO,(TEXT("[FTL:MSG] FTL_Open			[OK]\n")));


	return WMR_SUCCESS;
}

#if 0
typedef BOOL (*FMD_EraseFunc)(DWORD);
typedef BOOL (*FMD_SectorFunc)(DWORD , LPBYTE, PSectorInfo, DWORD);

//Visual: uniform read/write function
static void DSK_RWops(FMD_EraseFunc cleanfunc,FMD_SectorFunc opfunc,DWORD startSectorAddr, LPBYTE pSectorBuff,  DWORD dwNumSectors)
{
	DWORD blockID=0,block,badblocks=0;
	DWORD sector=0;

	block=sector2block(startSectorAddr);

	//get the number of  bad blocks
	while(blockID<block)
	{
		if(FMD_IsBlockBad(blockID))
			badblocks++;
	}

	//adjust
	startSectorAddr+=(badblocks*SECTOR_PER_BLOCK);
	block+=badblocks;

	blockID=block;
	while(dwNumSectors>0)
	{
		//check one block
		if(FMD_IsBlockBad(blockID))
		{
			blockID++;
			startSectorAddr+=SECTOR_PER_BLOCK;
			continue;
		}

		if(cleanfunc)
			if(!cleanfunc(blockID))
				continue;

		for(sector=0;((sector<SECTOR_PER_BLOCK) && (dwNumSectors>0));sector++)
		{
			opfunc(startSectorAddr,pSectorBuff, 0,1);
			pSectorBuff+=SECTOR_SIZE;
			startSectorAddr++;
			dwNumSectors--;
		}
	}
}



//Visual: function
void BLK_Read(DWORD startSectorAddr, LPBYTE pSectorBuff,  DWORD dwNumSectors)
{
	DSK_RWops(0,FMD_ReadSector,startSectorAddr, pSectorBuff, dwNumSectors);
}
void BLK_Write(DWORD startSectorAddr, LPBYTE pSectorBuff,  DWORD dwNumSectors)
{
	DSK_RWops(FMD_EraseBlock,FMD_WriteSector,startSectorAddr, pSectorBuff, dwNumSectors);
}
#endif
